package edos.prm.task;

import java.util.Set;

import edos.prm.actor.Actor;
import edos.prm.artifact.Artifact;
import edos.prm.artifact.Attribute;
import edos.prm.process.Environment;
import edos.prm.process.Process;
import edos.prm.process.ProcessAction;
import edos.prm.project.Project;
import edos.prm.project.Topic;
import edos.prm.role.Role;
import edos.prm.role.RoleException;
import edos.prm.util.Time;

/**
 * A {@code Task} is a process in execution.
 * <p>
 * The task encapsulates a process that has been instantiated and assigned
 * to an {@code Actor}. The actions of the process that get executed are
 * determined by the {@code Role}s that the actor has been assigned
 * 
 * @version 1.0.
 */
public interface Task extends Artifact {

	/**
	 * Return the project for which this task is running.
	 * 
	 * @return the project bound to this task.
	 */
	@Attribute
	public Project getProject();

	/**
	 * Indicates the process that is executed by this task.
	 * 
	 * @return the process bound to this task.
	 */
	public Process getProcess();

	/**
	 * The {@code Environment} of this task contains the execution state of
	 * the process. It maps variables in process descriptions to values. 
	 * 
	 * @return the {@code Environment} object for this task.
	 */
	public Environment getEnvironment();

	/**
	 * Return the actor responsible for this executing this task
	 * 
	 * @return the actor behing this task
	 */
	@Attribute
	public Actor getActor();

	/**
	 * Give the execution {@code Status} of this task.
	 * 
	 * @return the {@code Status} of this task
	 */
	@Attribute
	public Status getStatus();

	/**
	 * Return the {@code Time} at which the task is scheduled to start
	 * executing.
	 * 
	 * @return the task's start time.
	 */
	public Time getStartDate();

	/**
	 * Specifies the deadline for this task, by which time the task is
	 * scheduled to terminated its execution.
	 * 
	 * @return the task's end date.
	 */
	public Time getEndDate();

	/**
	 * Adds a break-point to the task at the specified process action.
	 * <p>
	 * The break-point is signaled just prior to execution of the action.
	 * 
	 * @param action the position at which the breakpoint had to be added.
	 * @return a unique identifier of the breakpoint
	 * @throws RoleException if the caller does not have the right to call
	 * this method.
	 */
	public int addBreakPoint(ProcessAction action) throws RoleException;

	/**
	 * Removes a breakpoint from the task's execution
	 * 
	 * @param breakpoint the identifier of the breakpoint being removed.
	 * @throws RoleException if the caller does not have the right to call
	 * this method.
	 */
	public void removeBreakPoint(int breakpoint) throws RoleException;

	/**
	 * Executes the task, running all underlying ProcessActions.
	 * 
	 * @throws RoleException if the caller does not have the right to start the
	 * task.
	 * @throws IllegalStateException if the task is not in the READY state
	 */
	public void execute() throws RoleException, IllegalStateException;

	/**
	 * Forces termination of the task.
	 *
	 *
	 * @throws RoleException if the caller does not have the right to stop
	 * this task.
	 * @throws IllegalStateException if the task is not in a STARED state.
	 */
	public void stop() throws RoleException, IllegalStateException;

	/**
	 * Rollbacks all the task's execution to a given breakpoint
	 * 
	 * @param breakpoint the point to which all ProcessActions 
	 * 		  have to be rollback-ed.
	 * @throws RoleException if the caller does not have the right to stop this
	 * task.  
	 */
	public void rollback(int breakpoint) throws RoleException;

	/**
	 * Suspend execution of this task.
	 *
	 * @throws RoleException if the caller does not have the right to suspend
	 * this task.
	 * @throws IllegalStateException if the task is not in a STARED state.
	 */
	public void suspend() throws RoleException, IllegalStateException;

	/**
	 * Resume the execution of this task
	 *
	 * @throws RoleException if the caller does not have the right to resume
	 * this task.
	 * @throws IllegalStateException if the task is not in a SUSPENDED state.
	 */
	public void resume() throws RoleException, IllegalStateException;

	/**
	 * 
	 */
	/**
	 * Returns the description of this task
	 * 
	 * @return the task's description
	 */
	@Attribute
	public String getDescription();

	/**
	 * Returns the name of this task
	 * 
	 * @return the String name of the task.
	 */
	@Attribute
	public String getName();

	/**
	 * A task has a status to indicate where it is in its execution.
	 */
	public enum Status {
		/**
		 * The task has been created and initialized; it has not yet been
		 * started.
		 */
		READY,
		/**
		 * The task is now running.
		 */
		STARTED,
		/**
		 * The task has been suspended.
		 */
		SUSPENDED,
		/**
		 * The task has terminated its execution.
		 */
		TERMINATED,
		/**
		 * The task has been stopped without going to the end of its
		 * execution.
		 */
		STOPPED;
	}

	public final class PrmTask implements Task {

		private edos.prm.process.Process process;
		private Time start, end;
		private Actor actor;
		private Project project;
		private Role role;
		private Status status;
		private String name;
		private String description;

		public static Task DefaultTask;

		static void setDefaultTask(Task task) {
			DefaultTask = task;
		}

		public PrmTask(Actor actor, Project project, Process process) {
			this.process = process;
			this.project = project;
			this.actor = actor;
			System.out.println("Running task " + process);
			name = process.getName();
		}

		public Actor getActor() {
			return actor;
		}

		public Time getEndDate() {
			return end;
		}

		public Process getProcess() {
			return process;
		}

		public Project getProject() {
			return project;
		}

		public Role getRole() {
			return role;
		}

		public Time getStartDate() {
			return start;
		}

		public Status getStatus() {
			return status;
		}

		public Environment getEnvironment() {
			return Environment.getEnvironmentFor(process);
		}

		public int addBreakPoint(ProcessAction action) {
			throw new UnsupportedOperationException();
		}

		public void execute() throws RoleException {
			process.getDeclaredActions().execute(null);
		}

		public String getDescription() {
			return description;
		}

		public String getName() {
			return name;
		}

		public Set<Topic> getTopics() {
			return this.project.getTopics();
		}

		public void removeBreakPoint(int breakpoint) {
			throw new UnsupportedOperationException();
		}

		public void rollback(int breakPointID) {
			throw new UnsupportedOperationException();
		}

		public void rollback() {
			throw new UnsupportedOperationException();
		}

		public void stop() {
			throw new UnsupportedOperationException();
		}

		public String toString() {
			return name;
		}

		public void resume() throws RoleException, IllegalStateException {
			// TODO Auto-generated method stub
			
		}

		public void suspend() throws RoleException, IllegalStateException {
			// TODO Auto-generated method stub
			
		}		
	}
}
